use std::cmp::max;
use std::sync::{mpsc, Arc, Mutex};
use std::{thread, time};
use std::thread::JoinHandle;
use std::time::Instant;

// 实现一个简单线程池
// 定义JOB 闭包获取所有权，允许在线程间传递，保证生命周期
type Job = Box<dyn FnOnce() + Send + 'static>;
type Message = Option<Job>;
struct Worker {
    id: usize,
    thread: Option<JoinHandle<()>>,
}

pub struct SimplePool {
    max_cnt: usize,                //最大线程数
    workers: Vec<Worker>,          // 工作线程数组
    sender: mpsc::Sender<Message>, //通过mpsc实现pool对工作线程操控
}

impl Worker {
    fn new(id: usize, rec: Arc<Mutex<mpsc::Receiver<Message>>>) -> Self {
        Worker {
            id,
            thread: Some(thread::spawn(move || loop {
                match rec.lock().unwrap().recv().unwrap() {
                    Some(job) => job(),
                    None => break,
                }
            })),
        }
    }
}

impl SimplePool {
    pub fn new(max_cnt: usize) -> Self {
        assert!(max_cnt > 0, "max_cnt must bigger than zero!");
        let (sender, rc) = mpsc::channel();
        let mut workers = Vec::with_capacity(max_cnt);
        let rec = Arc::new(Mutex::new(rc));
        for id in 0..max_cnt {
            workers.push(Worker::new(id, Arc::clone(&rec)));
        }

        SimplePool {
            max_cnt,
            workers,
            sender,
        }
    }
    pub fn execute<F>(&self, f: F)
    where
        F: FnOnce() + Send + 'static,
    {
        self.sender.send(Some(Box::new(f))).unwrap();
    }
}

impl Drop for SimplePool {
    fn drop(&mut self) {
        for _ in self.workers.iter() {
            self.sender.send(None).unwrap();
        }
        for worker in self.workers.iter_mut() {
            if let Some(handle) = worker.thread.take() {
                handle.join().unwrap();
            };
        }
    }
}

fn time_cost<F: FnOnce() + 'static>(f: F)  {
    let now = Instant::now();
    f();
    let duration = now.elapsed();
    println!("total time cost:");
    println!("cost {:?} ns",duration.as_nanos());
    println!("cost {:?} us",duration.as_micros());
    println!("cost {:?} ms",duration.as_millis());
    println!("cost {:?} ss",duration.as_secs());


}
fn ffa(intro: u128) -> u128 {
    match intro {
        x if x < 0 => 0,
        0 => 0,
        1 => 1,
        e => {
            let mut x: (u128, u128) = (0, 1);
            for _ in 2..=e {
                let i1 = x.0;
                x.0 = x.1;
                x.1 = i1 + x.0;
            }
            x.1
        }
    }
}


#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_works() {
        time_cost(|| {
            let mut vec= Vec::new();
            for x in 0..100000 {
                vec.push(100000-x);
            }
            vec.sort()


        });
    }
}
